using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections.Generic;
using System.Text;

using System.Web;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;

using Liberty.Controls.Rules;

[assembly: System.Web.UI.WebResource( "Liberty.Controls.WebControls.PageValidator.js", "text/javascript" )]

namespace Liberty.Controls.WebControls
{
    [Serializable]
    [Category( "Validation" )]
    public class PageValidator : WebControl
    {
        #region Constants
        private const string CREATE_RULE_SCRIPT = "var rule{0} = $create({1},{2});";
        #endregion

        #region Event Handlers
        #endregion

        #region Methods
        protected override void Render( HtmlTextWriter writer )
        {
            this.Writer = writer;
            this.ValidationRules.Clear();
            this.ProcessChildControls( this.Page.Controls );
            this.RenderValidationRules();
            this.RenderWebResources();
            base.Render( writer );
        }
        #endregion

        #region Properties
        public string PostbackControl
        {
            get
            {
                return i_PostbackControl;
            }
            set
            {
                i_PostbackControl = value;
            }
        }
        #endregion

        #region Private Methods
        private void ProcessChildControls( ControlCollection controls )
        {
            foreach( Control childControl in controls )
            {
                if ( childControl.Visible )
                {
                    if ( this.IsBaseValidator( childControl ) )
                    {
                        this.ValidationRules.Add( new ValidationRule( childControl.ClientID ) );
                    }
                    else if ( this.IsValidationSummaryControl( childControl ) )
                    {
                        ValidationSummary summaryControl = (ValidationSummary)childControl;
                        this.ValidationRules.Add( new ValidationSummaryRule( childControl.ClientID, summaryControl.ValidationGroup ) );
                    }
                }
                if (childControl.Controls.Count > 0)
                {
                    this.ProcessChildControls( childControl.Controls );
                }
            }
        }

        private bool IsBaseValidator( Control control )
        {
            return ( control is BaseValidator );
        }

        private bool IsValidationSummaryControl( Control control )
        {
            return ( control is ValidationSummary );
        }

        private void RenderValidationRules()
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
           
            StringBuilder stringBuilder = new StringBuilder();
            for( int i = 0; i < this.ValidationRules.Count; i++ )
            {
                stringBuilder.AppendLine( String.Format( CREATE_RULE_SCRIPT, i.ToString(), this.ValidationRules[i].GetType().ToString(),
                       serializer.Serialize( this.ValidationRules[i] ) ) );
            }

            ValidationRuleSet validationRuleSet = new ValidationRuleSet( this.ValidationRules
                , ( this.PostbackControl != String.Empty ) ? this.FindControl( this.PostbackControl ).ClientID : String.Empty );
            
            stringBuilder.AppendLine( validationRuleSet.Render() );
            this.Page.ClientScript.RegisterStartupScript( typeof( PageValidator ), "Rules", stringBuilder.ToString(), true );
        }

        private void RenderWebResources()
        {
            
        }
        #endregion

        #region Private Properties
        private HtmlTextWriter Writer
        {
            get
            {
                return this.I_Writer;
            }
            set
            {
                this.I_Writer = value;
            }
        }

        private List<AbstractRule> ValidationRules
        {
            get
            {
                if( this.i_ValidationRules == null )
                {
                    this.i_ValidationRules = new List<AbstractRule>();
                }
                return this.i_ValidationRules;
            }
        }
        #endregion

        #region Construction and Finalization
        public PageValidator()
        {
            this.PostbackControl = String.Empty;
        }
        #endregion

        #region Data Elements
        private HtmlTextWriter I_Writer;
        private List<AbstractRule> i_ValidationRules;
        private string i_PostbackControl;
        #endregion
    }
}
